# ============================================================================
# 编译器配置模块
# ============================================================================
# 提供编译器相关的统一配置
# ============================================================================

# C++ 标准配置
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# 根据是否构建工具设置 C++ 标准版本
if(CMAKE_BUILD_TOOLS)
    set(CMAKE_CXX_STANDARD 17)
else()
    set(CMAKE_CXX_STANDARD 11)
endif()

# 导出编译命令（用于 clangd、IDE 等工具）
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# 启用文件夹组织（在 IDE 中按文件夹组织）
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# Windows MSVC 特定配置
if(WIN32 AND MSVC)
    # 禁用编译器依赖跟踪（减少输出）
    set(CMAKE_C_DEPENDS_USE_COMPILER FALSE)
    set(CMAKE_CXX_DEPENDS_USE_COMPILER FALSE)
    
    # 修改编译规则，移除 /showIncludes，添加 /nologo
    set(CMAKE_C_COMPILE_OBJECT 
        "<CMAKE_C_COMPILER> /nologo <DEFINES> <INCLUDES> <FLAGS> /Fo<OBJECT> /Fd<TARGET_COMPILE_PDB> -c <SOURCE>"
        CACHE STRING "" FORCE)
    set(CMAKE_CXX_COMPILE_OBJECT 
        "<CMAKE_CXX_COMPILER> /nologo <DEFINES> <INCLUDES> <FLAGS> /Fo<OBJECT> /Fd<TARGET_COMPILE_PDB> -c <SOURCE>"
        CACHE STRING "" FORCE)
    
    # 设置终端代码页为 GBK（936）
    # 注意：这只是为了在 Windows 控制台正确显示中文输出，不影响编译器对源文件的编码处理
    # 编译器编码由下面的 /utf-8 选项控制
    execute_process(COMMAND cmd /c chcp 936 OUTPUT_QUIET ERROR_QUIET)
    
    # 设置 PDB 输出目录，避免多个目标写入同一个 PDB 文件
    set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pdb")
    set(CMAKE_PDB_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/pdb")
    set(CMAKE_PDB_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/pdb")
    set(CMAKE_PDB_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/pdb")
    set(CMAKE_PDB_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}/pdb")
    
    # 强制使用 /MTd（静态运行时库），避免库冲突
    if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.15")
        set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" CACHE STRING "MSVC runtime library" FORCE)
    endif()
    
    # 为每个目标设置独立的 PDB 文件名的函数
    function(set_target_pdb_name target_name)
        if(MSVC)
            set_target_properties(${target_name} PROPERTIES
                PDB_NAME "${target_name}"
                PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pdb"
            )
        endif()
    endfunction()
    
    # MSVC 编码配置
    # 🔥 关键：强制使用 UTF-8 编码，解决中文乱码问题
    # /utf-8 选项（MSVC 2015+）同时设置源文件和执行字符集为 UTF-8
    # 这确保所有源文件（无论原始编码）都被正确识别
    if(MSVC_VERSION VERSION_GREATER_EQUAL 1900)  # MSVC 2015 (14.0) 及以上
        add_compile_options(/utf-8)
        message(STATUS "✅ 已启用 UTF-8 编码支持 (/utf-8)")
    else()
        # MSVC 2013 及以下，使用分别设置的方式
        add_compile_options(/source-charset:utf-8 /execution-charset:utf-8)
        message(STATUS "✅ 已启用 UTF-8 编码支持 (/source-charset:utf-8 /execution-charset:utf-8)")
    endif()
    
    # MSVC 警告抑制
    add_compile_options(
        /wd4819  # 文件编码警告（已通过 /utf-8 解决，但保留以兼容旧代码）
        /wd4828  # 文件位置警告
        /wd4244  # 类型转换警告
        /wd4267  # 大小转换警告
        /wd4099  # 类型名冲突
        /wd4005  # 宏重定义
        /wd4200  # 非标准扩展
        /wd4065  # switch 语句中的 case 标签
        /wd4091  # 类型名被忽略
        /wd4251  # 类需要 dll 接口
        /wd4996  # 函数已弃用
        /wd4275  # 非 dll 接口类用作基类
        /wd4316  # 对象在堆上对齐
        /wd4018  # 有符号/无符号不匹配
        /wd4834  # 弃用的属性
        /wd4311  # 指针截断
        /wd4309  # 常量值被截断
        /wd4013  # 函数未定义
        /wd4024  # 参数类型不匹配
        /wd4477  # 格式字符串需要类型
        /wd4133  # 类型不匹配
        /wd4047  # 参数类型不同
        /wd4217  # 成员函数未声明为内联
        /wd4286  # 类型转换警告
        /wd4291  # 无匹配的删除运算符
        /wd4100  # 未使用的参数
    )
    
    # 强制移除所有 FLAGS 中的 /showIncludes
    foreach(flag_var 
        CMAKE_C_FLAGS CMAKE_CXX_FLAGS
        CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
        CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE
        CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO
        CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL
    )
        if(DEFINED ${flag_var})
            string(REPLACE "/showIncludes" "" ${flag_var} "${${flag_var}}")
            set(${flag_var} "${${flag_var}}" CACHE STRING "" FORCE)
        endif()
    endforeach()
    
    message(STATUS "✅ Windows MSVC 编译器配置已应用")
endif()

# Linux/macOS 编译器信息显示（编译器选择已在 CMakeLists.txt 的 project() 之前完成）
if(UNIX AND NOT WIN32)
    # 检查当前使用的编译器
    get_filename_component(COMPILER_NAME "${CMAKE_C_COMPILER}" NAME)
    if(COMPILER_NAME MATCHES "clang")
        message(STATUS "✅ 使用 Clang 编译器 ⚡")
    else()
        message(STATUS "✅ 使用 GCC 编译器")
    endif()
endif()

# 输出编译器信息
message(STATUS "C++ 标准: C++${CMAKE_CXX_STANDARD}")
message(STATUS "C 编译器: ${CMAKE_C_COMPILER}")
message(STATUS "C++ 编译器: ${CMAKE_CXX_COMPILER}")

